
package com.scalar.chiptrack.db;

import java.sql.Connection;

import javax.transaction.TransactionManager;

import tyrex.resource.jdbc.ConnectionPool;
import tyrex.tm.TransactionDomain;

import com.scalar.chiptrack.commons.Constants;
import com.scalar.chiptrack.utils.ConfigManager;


/**
 * Database Connection Pool Class for Transactions
 *
 * @author Balaram Putta
 * @version
 */
public final class DBTransaction
{

    private static TransactionDomain s_domain = null;
    private static TransactionManager s_txManager = null;
    private static ConnectionPool s_connPool = null;
    private static boolean printConnInfo = true;

    private DBTransaction () throws DBXException {
        init();
    }


    private void init() throws DBXException {

        try {

            if (s_domain == null) {

                // Create or get the reference of the transaction domain
                s_domain = TransactionDomain.getDomain (ConfigManager.getTxDomainName());
                if (s_domain == null) {
                    s_domain = TransactionDomain.createDomain (ConfigManager.getTxDomainCOnfigFile());
                }

                // Activate the domain if its not activated already...
                if (s_domain.getState() != TransactionDomain.ACTIVE) {
                    s_domain.recover();
                }
            }

            // Local database connection pool
            if (s_connPool == null) {
                s_connPool = (ConnectionPool) s_domain.getResources().getResource (ConfigManager.getTxDBResourceName());
            }

            if (s_txManager == null) {
                s_txManager = s_domain.getTransactionManager();
            }

        }

        catch (Exception e) {
            throw new DBXException (e.getMessage(), e);
        }
    }


    public void begin() throws DBXException {
        try {
            s_txManager.begin();
            //s_txManager.getTransaction().enlistResource (s_connPool.getXAResource());
        }
        catch (Exception e) {
            throw new DBXException (e.getMessage(), e);
        }
    }


    public Connection getConnection() throws DBXException
    {
        return getConnection( Constants.DATASOURCE_TYPE_LOCAL );
    }

    /**
     * Returns a database connection from the pool based on the datasource type
     *
     * @param datasourceType Either DATASOURCE_TYPE_GREAT_PLAINS or DATASOURCE_TYPE_LOCAL
     * @return Connection from DB pool
     * @throws DBXException
     */
    public Connection getConnection( int datasourceType ) throws DBXException
    {
        Connection conn = null;
        try
        {
			conn = s_connPool.getConnection();

            if( printConnInfo )
            {
                System.out.println( "DBTransaction URL... " + conn.getMetaData().getURL() + "\n" );
                printConnInfo = false;
            }
        }
        catch( Exception e )
        {
            throw new DBXException( e.getMessage(), e );
        }

        return conn;
    }


    public void commit() throws DBXException {
        try {
            s_txManager.commit();
            //printConnectionPoolMetrics();
        }
        catch (Exception e) {
            throw new DBXException (e.getMessage(), e);
        }
    }


    public void rollback() throws DBXException {
        try {
            s_txManager.rollback();
            //printConnectionPoolMetrics();
        }
        catch (Exception e) {
            throw new DBXException (e.getMessage(), e);
        }
    }


    public static DBTransaction getInstance() throws DBXException {
        return new DBTransaction();
    }

    public void printConnectionPoolMetrics() {

        System.out.println ("\n=====================================================\n");
        System.out.println ("available conn = " + s_connPool.getAvailable());
        System.out.println ("current unused = " + s_connPool.getCurrentUnused());
        System.out.println ("current used = " + s_connPool.getCurrentUsed());
        System.out.println ("total = " + s_connPool.getTotal());
        System.out.println ("total created = " + s_connPool.getTotalCreated());
        System.out.println ("total discareded = " + s_connPool.getTotalDiscarded());
        System.out.println ("\n=====================================================\n");
    }
}